using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Colman.Rpg.Connection;
using Colman.Rpg.Messaging;

namespace Colman.Rpg
{
    /// <summary>
    /// The character's stats sheet.
    /// </summary>
    public partial class CharacterSheetForm : Colman.Rpg.ConnectionAwareForm
    {
        private int addedToAP = 0, addedToDP = 0;
        private int initializing = 0;

        /// <summary>
        /// Creates a new instance of <see cref="CharacterSheetForm" />.
        /// </summary>
        public CharacterSheetForm()
        {
            InitializeComponent();
        }

        private void SetPlayer(Player player)
        {
            initializing++;

            try
            {
                this.lblName.Text = player.Name;
                this.lblLevel.Text = player.Level.ToString();
                this.lblXP.Text = player.XP.ToString();
                this.lblNextLevelAt.Text = player.ExperienceRemainingForNextLevel.ToString();
                this.lblAP.Text = player.AP.ToString();
                this.lblDP.Text = player.DP.ToString();

                List<Item> weapons = player.Items.FindAll(delegate(Item item) { return item is Weapon; });
                weapons.Insert(0, player.Weapon);

                this.cbWeapon.DataSource = weapons;
                this.cbWeapon.SelectedValue = player.Weapon.Name;

                List<Item> armors = player.Items.FindAll(delegate(Item item) { return item is Armor; });
                armors.Insert(0, player.Armor);

                this.cbArmor.DataSource = armors;
                this.cbArmor.SelectedValue = player.Armor.Name;
            }
            finally
            {
                initializing--;
            }
        }

        /// <summary>
        /// Sets the player in the form and the points that should be distributed to them.
        /// </summary>
        /// <param name="player">The player in the form.</param>
        /// <param name="pointsToDistribute">The points to distribute to the player.</param>
        public void SetPlayer(Player player, int pointsToDistribute)
        {
            this.SetPlayer(player);

            this.lblAvailablePoints.Text = pointsToDistribute.ToString();

            pnlAddPoints.Visible = (pointsToDistribute > 0);
        }

        /// <summary>
        /// Raises the <see cref="Form.Closing" /> event.
        /// </summary>
        /// <param name="e">An <see cref="EventArgs" /> that contains the event data.</param>
        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);

            if (!e.Cancel)
            {
                if (this.lblAvailablePoints.Text != "0")
                {
                    MessageBox.Show(this, "You must distribute all available points to your attack and/or defense.");
                    e.Cancel = true;
                }
            }
        }

        /// <summary>
        /// Raises the <see cref="Form.Closed" /> event.
        /// </summary>
        /// <param name="e">An <see cref="EventArgs" /> that contains the event data.</param>
        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);

            if (this.addedToAP != 0 ||
                this.addedToDP != 0)
            {
                ClientEndPoint.Instance.SendMessage(new PlayerPointsAdditionRequest(this.addedToAP, this.addedToDP));
            }
        }

        private void btnAddAP_Click(object sender, EventArgs e)
        {
            int pointsToDistribute = Convert.ToInt32(this.lblAvailablePoints.Text);

            this.addedToAP++;
            pointsToDistribute--;

            this.lblAvailablePoints.Text = pointsToDistribute.ToString();
            this.lblAP.Text = (Convert.ToInt32(this.lblAP.Text) + 1).ToString();

            pnlAddPoints.Visible = (pointsToDistribute > 0);
        }

        private void btnAddDP_Click(object sender, EventArgs e)
        {
            int pointsToDistribute = Convert.ToInt32(this.lblAvailablePoints.Text);

            this.addedToDP++;
            pointsToDistribute--;

            this.lblAvailablePoints.Text = pointsToDistribute.ToString();
            this.lblDP.Text = (Convert.ToInt32(this.lblDP.Text) + 1).ToString();

            pnlAddPoints.Visible = (pointsToDistribute > 0);
        }

        private void cbWeapon_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (initializing == 0)
            {
                this.cbWeapon.Enabled = false;
                Weapon selectedWeapon = ((Weapon)(((List<Item>)(this.cbWeapon.DataSource)).Find(delegate(Item item) { return (item.Name == this.cbWeapon.SelectedValue.ToString()); })));
                ClientEndPoint.Instance.SendMessage(new EquipWeaponRequest(selectedWeapon));
            }
        }

        private void cbArmor_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (initializing == 0)
            {
                this.cbArmor.Enabled = false;
                Armor selectedArmor = ((Armor)(((List<Item>)(this.cbArmor.DataSource)).Find(delegate(Item item) { return (item.Name == this.cbArmor.SelectedValue.ToString()); })));
                ClientEndPoint.Instance.SendMessage(new EquipArmorRequest(selectedArmor));
            }
        }

        /// <summary>
        /// Called when a message is received from the server.
        /// </summary>
        /// <param name="sender">The object that raised the event.</param>
        /// <param name="e">The message arguments.</param>
        protected override void OnMessageReceived(object sender, MessageReceivedEventArgs e)
        {
            base.OnMessageReceived(sender, e);

            ItemTransactionResponse response = e.Message as ItemTransactionResponse;

            if (response != null)
            {
                this.SetPlayer(response.Player);
            
                this.cbWeapon.Enabled = true;
                this.cbArmor.Enabled = true;
            }
        }
    }
}